﻿// -- FILE ------------------------------------------------------------------
// name       : CommandRepository.cs
// created    : Jani Giannoudis - 2008.04.15
// language   : c#
// environment: .NET 3.0
// --------------------------------------------------------------------------
using System;
using System.Windows.Input;
using System.Collections.Generic;
using System.Diagnostics;
using OpenExpressApp.WPF.Command;
using OpenExpressApp.Command;

namespace Itenso.Windows.Input
{

    // ------------------------------------------------------------------------
    public sealed class CommandRepository
    {


        // ----------------------------------------------------------------------
        private CommandRepository()
        {
        } // CommandRepository

        // 为了不让直接获取Command，而该为通过NewCommand实例化，把此方法该为私有
        private static CommandCollection Commands
        {
            get { return Instance.commands; }
        } // Commands

        public static CommandAdapter NewCommand(string name)
        {
            Command cmd = Commands[name];
            Debug.Assert(cmd is CommandAdapter, "只有OpenExpressApp的扩展Command才运行通过Repository新增");
            CommandBase coreCommand = Activator.CreateInstance((cmd as CommandAdapter).CoreCommand.GetType()) as CommandBase;
            var command = new CommandAdapter(coreCommand, typeof(CommandRepository), cmd.Description);

            return command;
        } // Commands

        public static bool Contains(string name)
        {
            return Commands.Contains(name);
        }

        public static CommandBinding CreateCommandBinding(Command cmd)
        {
            return new CommandBinding(
                cmd,
                new ExecutedRoutedEventHandler(CommandBindingExecuted),
                new CanExecuteRoutedEventHandler(CommandBindingCanExecute));
        }

        // ----------------------------------------------------------------------
        private static CommandRepository Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (mutex)
                    {
                        if (instance == null)
                        {
                            instance = new CommandRepository();
                        }
                    }
                }
                return instance;
            }
        } // Instance

        // ----------------------------------------------------------------------
        public static void AddRange(CommandCollection commands)
        {
            Instance.AddCommands(commands);
        } // AddRange

        // ----------------------------------------------------------------------
        public static void Add(Command command)
        {
            Instance.AddCommand(command);
        } // Add

        // ----------------------------------------------------------------------
        private void AddCommands(CommandCollection commands)
        {
            if (commands == null)
            {
                throw new ArgumentNullException("commands");
            }

            foreach (Command command in commands)
            {
                AddCommand(command);
            }
        } // AddCommands

        // ----------------------------------------------------------------------
        private void AddCommand(Command command)
        {
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }

            // command registration
            this.commands.Add(command);
        } // AddCommand

        // ----------------------------------------------------------------------
        private static void CommandBindingCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            Command command = e.Command as Command;
            if (command == null)
            {
                return;
            }

            // command can executed without CanExecute check
            if (!command.HasRequirements)
            {
                e.CanExecute = true;
                e.Handled = true;
                return;
            }

            // command context
            using (CommandContext commandContext =
                command.CreateCanExecuteContext(sender, e.OriginalSource, e.Parameter))
            {
                if (commandContext == null)
                {
                    return;
                }

                // command can execute check
                e.CanExecute = command.CanExecute(commandContext);
                e.Handled = true;
            }
        } // CommandBindingCanExecute

        // ----------------------------------------------------------------------
        private static void CommandBindingExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            Command command = e.Command as Command;
            if (command == null)
            {
                return;
            }

            // command context
            using (CommandContext commandContext =
                command.CreateCanExecuteContext(sender, e.OriginalSource, e.Parameter))
            {
                // command execute
                command.Execute(commandContext);
                e.Handled = true;
            }
        } // CommandBindingExecuted

        // ----------------------------------------------------------------------
        // members
        private readonly CommandCollection commands = new CommandCollection();
        private readonly CommandBindingCollection bindings = new CommandBindingCollection();

        private static readonly object mutex = new object();
        private static CommandRepository instance;

    } // class CommandRepository

} // namespace Itenso.Windows.Input
// -- EOF -------------------------------------------------------------------
